#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "data_codec.h"

#define CONFIG_ZEPHYR
#define TEST_TIMEOUT_MS (100)

// 根据不同的平台包含不同的头文件
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#define SLEEP(ms) Sleep(ms)
#elif defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#define SLEEP(ms) usleep((ms) * 1000)
#elif defined(CONFIG_ZEPHYR)
#include <zephyr/kernel.h>
#define SLEEP(ms) k_msleep(ms)
#else
#error "Unsupported platform"
#endif

void my_log_function(log_level_t level, const char *format, va_list args)
{
    const char *level_str = "";
    switch (level)
    {
        case LOG_ERROR:
            level_str = "ERROR";
            break;
        case LOG_INFO:
            level_str = "INFO";
            break;
        case LOG_DEBUG:
            level_str = "DEBUG";
            break;
        default:
            break;
    }
    printf("[%s] ", level_str);
    vprintf(format, args);
    printf("\n");
}

// 生成数据包
void generate_packet(uint16_t seq, uint16_t cmd, uint8_t *data, size_t data_len, uint8_t *buffer, size_t *len)
{
    if (sizeof(pkt_t) + data_len > MAX_PACKET_SIZE)
    {
        printf("Data length exceeds MAX_PACKET_SIZE");
        return;
    }
    uint8_t pkt_buf[MAX_PACKET_SIZE];
    pkt_t *pkt = (pkt_t *)pkt_buf;
    pkt->header = HEADER_SYNC;
    pkt->len = sizeof(pkt_t) + data_len;
    pkt->crc = 0; // CRC will be calculated in encode function
    pkt->seq = seq;
    pkt->cmd = cmd;
    pkt->data_len = data_len;

    if (data_len > 0)
    {
        memcpy(pkt->data, data, data_len);
    }

    data_codec_t codec;
    data_codec_init(&codec, LOG_NONE, NULL);
    codec.encode(pkt, pkt->data, buffer, len);
}

// 生成随机数据
void generate_random_data(uint8_t *data, size_t len)
{
    for (size_t i = 0; i < len; ++i)
    {
        data[i] = rand() % 256;
    }
}

// 打印解析到的数据包
void print_decoded_packet(const pkt_t *pkt)
{
    printf("Decoded packet: header=%04x, len=%d, seq=%d, cmd=%d, data_len=%d, data=",
           pkt->header, pkt->len, pkt->seq, pkt->cmd, pkt->data_len);
    for (size_t i = 0; i < pkt->data_len; i++)
    {
        printf("%02x ", pkt->data[i]);
    }
    printf("\n");
}

// 测试正常包
void test_normal_packet(data_codec_t *codec)
{
    printf("Starting normal packet test...\n");
    for (int i = 0; i < 10; ++i)
    {
        uint8_t buffer[MAX_PACKET_SIZE];
        size_t len;
        uint8_t data[10];
        generate_random_data(data, sizeof(data));
        generate_packet(rand() % 1000, rand() % 100, data, sizeof(data), buffer, &len);

        pkt_t decoded_pkt;
        int result = codec->decode(buffer, len, &decoded_pkt);

        if (result == 0)
        {
            print_decoded_packet(&decoded_pkt);
        }
        else
        {
            printf("Failed to decode packet\n");
        }
        SLEEP(TEST_TIMEOUT_MS);
    }
    printf("Normal packet test completed.\n");
}

// 测试粘包
void test_sticky_packet(data_codec_t *codec)
{
    printf("Starting sticky packet test...\n");
    for (int i = 0; i < 10; ++i)
    {
        uint8_t buffer1[MAX_PACKET_SIZE], buffer2[MAX_PACKET_SIZE];
        size_t len1, len2;
        uint8_t data1[10], data2[10];
        generate_random_data(data1, sizeof(data1));
        generate_random_data(data2, sizeof(data2));
        generate_packet(rand() % 1000, rand() % 100, data1, sizeof(data1), buffer1, &len1);
        generate_packet(rand() % 1000, rand() % 100, data2, sizeof(data2), buffer2, &len2);

        if (len1 + len2 > sizeof(buffer1))
        {
            printf("Sticky buffer size exceeds MAX_PACKET_SIZE");
            continue;
        }

        uint8_t sticky_buffer[MAX_PACKET_SIZE * 2];
        memcpy(sticky_buffer, buffer1, len1);
        memcpy(sticky_buffer + len1, buffer2, len2);

        pkt_t decoded_pkt;
        size_t offset = 0;

        while (offset < len1 + len2)
        {
            int result = codec->decode(sticky_buffer + offset, len1 + len2 - offset, &decoded_pkt);
            if (result == 0)
            {
                print_decoded_packet(&decoded_pkt);
                offset += decoded_pkt.len;
            }
            else
            {
                break;
            }
        }
        SLEEP(TEST_TIMEOUT_MS);
    }
    printf("Sticky packet test completed.\n");
}

// 测试分包
void test_fragmented_packet(data_codec_t *codec)
{
    printf("Starting fragmented packet test...\n");
    for (int i = 0; i < 10; ++i)
    {
        uint8_t buffer[MAX_PACKET_SIZE];
        size_t len;
        uint8_t data[10];
        generate_random_data(data, sizeof(data));
        generate_packet(rand() % 1000, rand() % 100, data, sizeof(data), buffer, &len);

        pkt_t decoded_pkt;

        // 模拟分片接收数据包
        size_t fragment_size = len / 2;
        if (fragment_size > sizeof(buffer))
        {
            printf("Fragment size exceeds buffer size");
            continue;
        }

        int result = codec->decode(buffer, fragment_size, &decoded_pkt);
        if (result != 0)
        {
            result = codec->decode(buffer + fragment_size, len - fragment_size, &decoded_pkt);
            if (result == 0)
            {
                print_decoded_packet(&decoded_pkt);
            }
            else
            {
                printf("Failed to decode fragmented packet\n");
            }
        }
        SLEEP(TEST_TIMEOUT_MS);
    }
    printf("Fragmented packet test completed.\n");
}

// 测试错误包
void test_error_packet(data_codec_t *codec)
{
    printf("Starting error packet test...\n");
    for (int i = 0; i < 10; ++i)
    {
        uint8_t buffer[MAX_PACKET_SIZE];
        size_t len;
        uint8_t data[10];
        generate_random_data(data, sizeof(data));
        generate_packet(rand() % 1000, rand() % 100, data, sizeof(data), buffer, &len);

        // 引入错误
        buffer[5] = 0xFF;

        pkt_t decoded_pkt;
        int result = codec->decode(buffer, len, &decoded_pkt);

        if (result == 0)
        {
            printf("Unexpectedly succeeded in decoding an error packet\n");
        }
        else
        {
            printf("Failed to decode packet, as expected\n");
        }
        SLEEP(TEST_TIMEOUT_MS);
    }
    printf("Error packet test completed.\n");
}

int main(void)
{
    // 使用固定种子来确保每次运行结果一致
    srand(12345);

    data_codec_t codec;
    data_codec_init(&codec, LOG_INFO, my_log_function);

    printf("Data Codec Version: %s\n", data_codec_get_version());

    for (int i = 0; i < 10; i++)
    {
        printf("Starting tests...\n");
        test_normal_packet(&codec);
        test_sticky_packet(&codec);
        test_fragmented_packet(&codec);
        test_error_packet(&codec);
        printf("All tests completed.\n");
    }

    return 0;
}
